package cn.flying.cloud.oauth.server.configuration.handler;

import javax.annotation.Resource;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import java.io.IOException;
import java.io.PrintWriter;
import java.text.ParseException;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.security.core.Authentication;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.web.authentication.logout.SimpleUrlLogoutSuccessHandler;
import org.springframework.stereotype.Component;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONWriter;
import com.nimbusds.jwt.JWT;
import com.nimbusds.jwt.JWTParser;
import com.nimbusds.jwt.SignedJWT;

import cn.flying.cloud.base.common.constants.Constants;
import cn.flying.cloud.base.common.enums.RtCodeEnum;
import cn.flying.cloud.base.common.vo.Rt;
import cn.flying.cloud.base.redis.service.RedisService;

/**
 * 登出成功处理类
 *
 * @author: admin
 * @date: 2023年05月27日 10:47
 * @version: 1.0
 */
@Component
public class CustomLogoutSuccessHandler extends SimpleUrlLogoutSuccessHandler {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Resource
    private RedisService redisService;
    @Resource
    private TokenStore tokenStore;

    @Override
    public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
        logger.info("用户退出登录成功！");

        Rt rt = Rt.success(RtCodeEnum.R10006.getDesc());
        String token = request.getHeader(HttpHeaders.AUTHORIZATION);
        if (StringUtils.isNotBlank(token)) {
            String access_token = token.replace("Bearer ", "");

            OAuth2AccessToken oAuth2AccessToken = tokenStore.readAccessToken(access_token);
            if (oAuth2AccessToken != null) {
                // 移除access_token
                tokenStore.removeAccessToken(oAuth2AccessToken);
                if (oAuth2AccessToken.getRefreshToken() != null) {
                    // 移除refresh_token
                    tokenStore.removeRefreshToken(oAuth2AccessToken.getRefreshToken());
                    logger.info("用户退出登录，并移除Token");
                }
            }

            // 删除redis
            JWT jwt = null;
            try {
                jwt = JWTParser.parse(access_token);
            } catch (ParseException e) {
                rt = Rt.error();
                logger.error("用户退出登录，解析Token失败", e);
            }
            Map<String, Object> object = ((SignedJWT) jwt).getPayload().toJSONObject();
            String jti = (String) object.get("jti");
            String tokenKey = Constants.ACCESS_TOKEN + ":" + jti;
            redisService.del(tokenKey);
        }

        response.setContentType("application/json;charset=utf-8");
        PrintWriter out = response.getWriter();
        out.write(JSON.toJSONString(rt, JSONWriter.Feature.WriteMapNullValue));
        out.flush();
        out.close();
    }
}
